package com.sky.service.admin.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.mapper.admin.ReportMapper;
import com.sky.service.admin.ReportService;
import com.sky.vo.*;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author bo.li
 * @Date 2024/10/22 11:33
 * @Version 1.0
 */
@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private ReportMapper reportMapper;

    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate> allDays = getAllDays(begin, end);

        //定义金额集合
        List<BigDecimal> amountList = new ArrayList<>();

        //按天查询金额[{"2024-01-01":22},{"2024-01-03":33}] ,有可能有缺失的日期
        List<OrderDayAmountVo> orderDayAmountVos = reportMapper.turnoverStatistics(begin, end.plusDays(1));
        //封装每天的订单金额数据
        for (LocalDate oneDay : allDays) {

            OrderDayAmountVo first = orderDayAmountVos.stream().filter(o -> o.getOrderTime().equals(oneDay)).findFirst().orElse(null);
            if(first == null){
                amountList.add(new BigDecimal(0));
            }else{
                amountList.add(first.getAmount());
            }
        }

        //封装结果
        TurnoverReportVO reportVO = TurnoverReportVO.builder().dateList(StringUtils.collectionToCommaDelimitedString(allDays))
                .turnoverList(StringUtils.collectionToCommaDelimitedString(amountList)).build();
        return reportVO;
    }

    @Override
    public OrderReportVO orderStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate> allDays = getAllDays(begin, end);
        //每日订单数   每日日有效订单
        List<Integer> totalList = new ArrayList<>();
        List<Integer> completeList = new ArrayList<>();

        List<OrderDayAmountVo> orderDayAmountVos = reportMapper.orderStatisitcs(begin, end.plusDays(1));

        for (LocalDate oneDay : allDays) {
            OrderDayAmountVo orderDayAmountVo = orderDayAmountVos.stream().filter(o -> o.getOrderTime().equals(oneDay)).findFirst().orElse(null);
            if(orderDayAmountVo == null){
                totalList.add(0);
                completeList.add(0);
            }else{
                totalList.add(orderDayAmountVo.getTotalNum());
                completeList.add(orderDayAmountVo.getCompleteNum());
            }
        }
        //订单总数
        Integer totalNum = totalList.stream().reduce(Integer::sum).get();
        Integer complete = completeList.stream().reduce(Integer::sum).get();
        double rate = 0d;
        if(totalNum != 0){
            rate= (double)complete / totalNum;
        }

        //封装返回
        OrderReportVO reportVO = OrderReportVO.builder().dateList(StringUtils.collectionToCommaDelimitedString(allDays))
                .validOrderCountList(StringUtils.collectionToCommaDelimitedString(completeList))
                .orderCountList(StringUtils.collectionToCommaDelimitedString(totalList))
                .totalOrderCount(totalNum)
                .validOrderCount(complete)
                .orderCompletionRate(rate)
                .build();
        return reportVO;
    }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {

        List<GoodsSalesDTO> salesDTOS = reportMapper.dishTop10(begin, end.plusDays(1));
        //获取菜品集合
        List<String> nameList = salesDTOS.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        //获取数量集合
        List<Integer> numList = salesDTOS.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());

        //构造返回参数
        SalesTop10ReportVO reportVO = SalesTop10ReportVO.builder()
                .nameList(StringUtils.collectionToCommaDelimitedString(nameList))
                .numberList(StringUtils.collectionToCommaDelimitedString(numList)).build();
        return reportVO;
    }

    @Override
    public void exportBusinessData(HttpServletResponse response) throws IOException {
        LocalDate now = LocalDate.now();
        LocalDate begin = now.minusDays(30);

        //一定读取excel文件，然后准备数据，一个一个给他填上去即可.
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表.xlsx");

        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        XSSFSheet sheet = workbook.getSheetAt(0);

        //设置时间
        XSSFRow row = sheet.getRow(1);
        row.getCell(0).setCellValue("时间：" + begin + " 至 " + now);
        //写概览数据
        OrderDayAmountVo orderDayAmountVo = reportMapper.orderExportBaseData(begin, now);
        BusinessDataVO dataVO = buildBusinessData(orderDayAmountVo, now);

        XSSFRow row4 = sheet.getRow(3);
        row4.getCell(1).setCellValue(dataVO.getTurnover());
        row4.getCell(3).setCellValue(dataVO.getOrderCompletionRate());
        row4.getCell(5).setCellValue(dataVO.getNewUsers());

        XSSFRow row5 = sheet.getRow(4);
        row5.getCell(1).setCellValue(dataVO.getValidOrderCount());
        row5.getCell(3).setCellValue(dataVO.getUnitPrice());

        int beginIndex = 7;
        //获取每天的订单数据
        List<OrderDayAmountVo> orderDayAmountVos = reportMapper.orderStatisitcs(begin, now);
        while(!begin.equals(now)){
            LocalDate tempDate = begin;
            OrderDayAmountVo dayAmountVo = orderDayAmountVos.stream().filter(o -> o.getOrderTime().equals(tempDate)).findFirst().orElse(null);
            dataVO = buildBusinessData(dayAmountVo, begin);
            XSSFRow dataRow = sheet.getRow(beginIndex);
            dataRow.getCell(0).setCellValue(begin.toString());
            dataRow.getCell(1).setCellValue(dataVO.getTurnover());
            dataRow.getCell(2).setCellValue(dataVO.getValidOrderCount());
            dataRow.getCell(3).setCellValue(dataVO.getOrderCompletionRate());
            dataRow.getCell(4).setCellValue(dataVO.getUnitPrice());
            dataRow.getCell(5).setCellValue(dataVO.getNewUsers());

            beginIndex++;
            begin = begin.plusDays(1);
        }

        workbook.write(response.getOutputStream());

        workbook.close();
    }


    private BusinessDataVO buildBusinessData(OrderDayAmountVo amountVo,LocalDate date){
        //封装新增用户数
        Integer newUser = reportMapper.getNewUser(date);
        if(amountVo == null){
            return new BusinessDataVO(0d,0,0d,0d,newUser);
        }
        int completeNum = amountVo.getCompleteNum();
        int totalNum = amountVo.getTotalNum();
        double price = 0;
        if(completeNum != 0) {
            price = amountVo.getAmount().doubleValue() / completeNum;
        }

        BusinessDataVO businessDataVO = BusinessDataVO.builder().validOrderCount(completeNum)
                .turnover(amountVo.getAmount().doubleValue())
                .orderCompletionRate((double) completeNum / totalNum)
                .unitPrice(price)
                .newUsers(newUser).build();

        return businessDataVO;
    }

    private List<LocalDate> getAllDays(LocalDate begin,LocalDate end){
        List<LocalDate> allDays = new ArrayList<>();
        allDays.add(begin);
        while (!begin.equals(end)){
            begin = begin.plusDays(1);
            allDays.add(begin);
        }
        return allDays;
    }
}